package ar.uba.fi.algo3.algoflight.model.juego;

import java.util.ArrayList;
import java.util.List;

import ar.uba.fi.algo3.algoflight.exceptions.NoHayPistasCompatiblesException;
import ar.uba.fi.algo3.algoflight.model.Posicion;
import ar.uba.fi.algo3.algoflight.model.aviones.Avion;
import ar.uba.fi.algo3.algoflight.model.formas.Figura;
import ar.uba.fi.algo3.algoflight.model.formas.Rectangulo;
import ar.uba.fi.algo3.algoflight.model.pistas.Pista;
import ar.uba.fi.algo3.algoflight.model.utils.Constantes;
import ar.uba.fi.algo3.algoflight.model.utils.Utilidades;
import fiuba.algo3.titiritero.modelo.ObjetoPosicionable;
import fiuba.algo3.titiritero.modelo.ObjetoVivo;

public class Escenario implements ObjetoVivo, ObjetoPosicionable {
	private List<Pista> listaPistas;
	private List<Avion> listaAviones;
	private int cantidadAvionesAAterrizar;
	private int cantidadAvionesAterrizados;
	private LanzadorDeAviones lanzadorDeAviones;
	private boolean escenarioCompletado;
	private Figura forma;

	public Escenario(NivelDeDificultad nivelDeDificultad) {
		listaPistas = new ArrayList<Pista>();
		listaAviones = new ArrayList<Avion>();
		cantidadAvionesAterrizados = 0;
		cantidadAvionesAAterrizar = nivelDeDificultad
				.getCantidadDeAvionesAAterrizar();
		lanzadorDeAviones = new LanzadorDeAviones(nivelDeDificultad, this);
		forma = new Rectangulo(Constantes.ANCHO_ESCENARIO,
				Constantes.ALTO_ESCENARIO);
	}

	public Posicion getTamanioPerimetro() {
		return forma.getTamanioPerimetro();
	}

	public void agregarAvion(Avion avion) {
		listaAviones.add(avion);
	}

	public void agregarPista(Pista pista) {
		listaPistas.add(pista);
	}

	public void quitarAvion(Avion avion) {
		listaAviones.remove(avion);
	}

	public List<Avion> getListaAviones() {
		return listaAviones;
	}

	public List<Pista> getListaPistas() {
		return listaPistas;
	}

	public boolean hayColisiones() {
		boolean resultado = false;

		int mitadTamanioArray = (listaAviones.size() % 2) == 0 ? listaAviones
				.size() / 2 : (listaAviones.size() / 2) + 1;

		for (int i = 0; i < mitadTamanioArray; i++) {
			for (int j = listaAviones.size() - 1; j > i; j--) {
				resultado = listaAviones.get(i)
						.hayColision(listaAviones.get(j));
				if (resultado == true) {
					return resultado;
				}
			}
		}
		return resultado;
	}

	public boolean aterrizarAviones() {
		boolean aterrizado = false;
		List<Avion> aterrizados = new ArrayList<Avion>();

		for (Avion avion : listaAviones) {
			for (Pista pista : listaPistas) {
				if (pista.posicionDeAterrizajeValida(avion.getPosicion())
						&& avion.puedeAterrizarEn(pista)) {
					cantidadAvionesAterrizados++;
					aterrizados.add(avion);
					aterrizado = true;
				}
			}
		}

		for (Avion avion : aterrizados) {
			listaAviones.remove(avion);
		}
		return aterrizado;
	}

	public boolean completado() {
		if (cantidadAvionesAterrizados == cantidadAvionesAAterrizar) {
			escenarioCompletado = true;
			lanzadorDeAviones.detener();
		}
		return escenarioCompletado;
	}

	public int getCantidadAvionesAAterrizar() {
		return cantidadAvionesAAterrizar;
	}

	public Pista getPistaCompatible(Avion avion)
			throws NoHayPistasCompatiblesException {
		List<Pista> pistasCompatibles = new ArrayList<Pista>();

		for (Pista pista : listaPistas) {
			if (avion.puedeAterrizarEn(pista)) {
				pistasCompatibles.add(pista);
			}
		}

		if (pistasCompatibles.isEmpty()) {
			throw new NoHayPistasCompatiblesException();
		} else {
			return pistasCompatibles.get(Utilidades
					.generarRandom(pistasCompatibles.size()));
		}

	}

	public static boolean estaDentroLimitesDelEscenario(Posicion posicion,
			Figura forma) {

		Posicion tamanio = forma.getTamanioPerimetro();
		float x = posicion.getCoordX() + tamanio.getCoordX();
		float y = posicion.getCoordY() - tamanio.getCoordY();
		return ((posicion.getCoordX() >= 0)
				&& (x <= Constantes.ANCHO_ESCENARIO) && (y >= 0) && (posicion
				.getCoordY() <= Constantes.ALTO_ESCENARIO));
	}

	@Override
	public void vivir() {

		if (!hayColisiones()) {
			if (!completado()) {
				for (Avion avion : listaAviones) {
					avion.vivir();
				}
				aterrizarAviones();
				lanzadorDeAviones.avanzarTiempo();
			}
		} else {
			lanzadorDeAviones.detener();
			System.out.println("PERDISTE");
		}
	}

	@Override
	public int getX() {
		return 0;
	}

	@Override
	public int getY() {
		return 0;
	}

	public Avion getAvionEnPosicion(Posicion posicion) {
		for (Avion avion : listaAviones) {
			if (avion.getPosicion().estaCercaDe(posicion, 20)) {
				return avion;
			}
		}
		return null;
	}
}
